package com.pf.auth.provider;

import com.pf.auth.model.dto.ClientDetailsDto;
import com.pf.auth.service.IClientProvider;
import com.pf.base.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.ClientAlreadyExistsException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientRegistrationService;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: auth
 * @description:
 * @author: wj
 * @create: 2021-04-12 15:08
 **/
@Slf4j
@DubboService
public class ClientDetailsProvider implements IClientProvider {

    @Autowired
    private JdbcClientDetailsService jdbcClientDetailsService;

    public List<ClientDetailsDto> list() {

        List<ClientDetails> list = jdbcClientDetailsService.listClientDetails();
        if (list != null) {
            return list.stream().map(clientDetails -> {
                return buildClientDetailsDto((BaseClientDetails) clientDetails);
            }).collect(Collectors.toList());
        }
        return null;
    }
    private static ClientDetailsDto buildClientDetailsDto(BaseClientDetails clientDetails) {
        ClientDetailsDto vo = new ClientDetailsDto();
        vo.setClientId( clientDetails.getClientId() );
        vo.setClientSecret(clientDetails.getClientSecret());
//        vo.setScope(clientDetails.getScope());
        vo.setResourceIds(clientDetails.getResourceIds());
        vo.setAuthorizedGrantTypes(clientDetails.getAuthorizedGrantTypes());
        vo.setRegisteredRedirectUris(clientDetails.getRegisteredRedirectUri());
//        vo.setAutoApproveScopes(clientDetails.getAutoApproveScopes());
        vo.setAuthorities(new ArrayList<>(clientDetails.getAuthorities()));
        vo.setAccessTokenValiditySeconds(clientDetails.getAccessTokenValiditySeconds());
        vo.setRefreshTokenValiditySeconds(clientDetails.getRefreshTokenValiditySeconds());
        vo.setAdditionalInformation(clientDetails.getAdditionalInformation());
        return vo;
    }
    public CommonResult<Boolean> add(ClientDetailsDto vo) {

        try {
            jdbcClientDetailsService.addClientDetails(convertBaseClientDetails(vo));
        } catch (ClientAlreadyExistsException e) {
            return CommonResult.failed(e.getMessage());
        }
        return CommonResult.success();
    }
    private BaseClientDetails convertBaseClientDetails(ClientDetailsDto vo) {
        return new BaseClientDetails(
                vo.getClientId(),
                StringUtils.collectionToCommaDelimitedString(vo.getResourceIds()),
                ClientDetailsDto.Scope,
                StringUtils.collectionToCommaDelimitedString(vo.getAuthorizedGrantTypes()),
                StringUtils.collectionToCommaDelimitedString(vo.getAuthorities()),
                StringUtils.collectionToCommaDelimitedString(vo.getRegisteredRedirectUris())
        );
    }
    public CommonResult<Boolean> update(ClientDetailsDto vo) {
        try {
            jdbcClientDetailsService.updateClientDetails(convertBaseClientDetails(vo));
        } catch (NoSuchClientException e) {
            return CommonResult.failed(e.getMessage());
        }
        return CommonResult.success();
    }
    public CommonResult<Boolean> updateSecret(ClientDetailsDto vo) {

        try {
            jdbcClientDetailsService.updateClientSecret(vo.getClientId(), vo.getClientSecret());
        } catch (NoSuchClientException e) {
            return CommonResult.failed(e.getMessage());
        }
        return CommonResult.success();
    }
    public CommonResult<Boolean> delete(String clientId) {

        try {
            jdbcClientDetailsService.removeClientDetails(clientId);
        } catch (NoSuchClientException e) {
            return CommonResult.failed(e.getMessage());
        }
        return CommonResult.success();
    }

}
